#include <board.h>
#include <board_memories.h>
#include <tsd/tsd.h>
#include <tsd/inarea.h>
#include <lcd/lcdd.h>
#include <lcd/draw.h>
#include <lcd/font.h>
#include <pit/pitd.h>
#include <pio/pio.h>
#include <menu.h>
#include <menu_list.h>
#include <viewer.h>
#include <memories/MEDSdcard.h>
#include <string.h>
#include <clock.h>
#include <cache.h>

static unsigned char *_lcd_buffer[BOARD_LCD_HEIGHT * BOARD_LCD_WIDTH * 3];

//------------------------------------------------------------------------------
// VIEWER

static char selected[MENU_ITEM_NAME_LENGTH];

static inline void viewer (void) {
    viewer_open(selected);
}

//------------------------------------------------------------------------------
// MENU

static menu_list_t items;

static void selection (int idx) {
    menu_item_t item;

    if (idx == MENU_BACK) {
        f_chdir("..");
        goto _menu_config_new_items;
    }

    menu_list_get(&item, &items, idx);

    if (item.flags & MENU_ITEM_IS_DIR) {
        f_chdir(item.name);
        _menu_config_new_items:
        menu_list_init(&items, ".");
        menu_configure_items(&items);
        return;
    }

    menu_exit();

    strcpy(selected, item.name);
}

static void menu (void) {
    menu_configure_items(&items);
    menu_draw(_lcd_buffer);
}

//------------------------------------------------------------------------------
// MAIN

Media sdcard;

#define DRAW_WELCOM_SCREEN_LINE(line, column, str) { \
    LCDD_DrawString(_lcd_buffer, \
            5 + (column * 12), \
            1 + (line * 17), \
            str, \
            COLOR_BLACK); \
}

static inarea_rect_t _conf_rect = { .x = 0, .y = 0, .width = BOARD_LCD_WIDTH, .height = BOARD_LCD_HEIGHT };
static volatile int _conf_flag;
static void _conf_func (inarea_rect_t * pRect) {
    _conf_flag = 0;
}

static inline void show_welcome_screen (void) {
    _conf_flag = 1;
    LCDD_Fill(_lcd_buffer, COLOR_WHITE);
    /*  The welcome-screen can hold fourteen lines
            counted from 0 to 13
        Each line can contain 26 characters
            "example line with 26 chars" */
    DRAW_WELCOM_SCREEN_LINE( 1, 2,
            "----------------------");
    DRAW_WELCOM_SCREEN_LINE( 2, 4,
            "--  d264player  --");
    DRAW_WELCOM_SCREEN_LINE( 5, 1,
            "Please insert an SD card");
    DRAW_WELCOM_SCREEN_LINE( 6, 3,
            "and touch the screen");
    DRAW_WELCOM_SCREEN_LINE( 7, 7,
            "to continue.");
    DRAW_WELCOM_SCREEN_LINE(11, 0,
            "Alexandre Goncalves  31788");
    LCDD_DrawChar(_lcd_buffer, 163, 191, ',', COLOR_BLACK);
    DRAW_WELCOM_SCREEN_LINE(12, 0,
            "Danilo Tiago         29586");
    DRAW_WELCOM_SCREEN_LINE(13, 0,
            "Tiago Rodrigues      30075");

    TSD_InareaAdd(0, 0, _conf_func, &_conf_rect, 1);
    PITD_Configure(TSD_Update_PenState, 100000, 1);
    TSD_SetPitPeriod(100);
    // Wait for SD card.
    MEDSdcard_Initialize(&sdcard, 1);
    // Wait for touch.
    PITD_Start();
    while (_conf_flag);
    PITD_Stop();
    TSD_InareaRemoveAll();
}

int main() {
    FATFS fs = {0};
    //CLOCK_SetConfig(1);
    cache_enable();

    // Initialize LCD
    LCDD_Fill(_lcd_buffer, COLOR_WHITE);
    LCDD_Initialize();
    LCDD_DisplayBuffer(_lcd_buffer);

#if !defined(sdram)
    BOARD_ConfigureSdram(BOARD_SDRAM_BUSWIDTH);
#endif

    TSD_Initialize(0);
    PITD_Configure(TSD_Update_PenState, 10000, 0);
    TSD_SetPitPeriod(10);
    PITD_Start();
    while (!TSD_Calibrate(_lcd_buffer))
        ;
    PITD_Stop();

    show_welcome_screen();
    f_mount(DRV_MMC, &fs);
    f_chdrive(DRV_MMC);
    f_chdir("0:");

    LCDD_Fill(_lcd_buffer, COLOR_WHITE);
    viewer_init();
    menu_init();
    menu_configure_callback(selection);

    menu_list_init(&items, ".");

    while (1) {
        menu();
        viewer();
    }

    return 0;
}
